/* 
 * Copyright (C) 2013 National University of Defense Technology(NUDT) & Kylin Ltd. 
 * 
 * Authors: 
 *  Kobe Lee   kobe24_lixiang@126.com
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "activation_dbus.h"
#include "activation_dbus_glue.h"
#include "hardware_info.h"
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "marshal.h"
#include <sys/timeb.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#include<kylin-activation.h>
#include <unistd.h>

enum
{
  ACTIVATION_RESULT,
  LAST_SIGNAL
};

static guint signals[LAST_SIGNAL] = { 0 };

extern kylin_activation_trial_status(int * result);

typedef void*(*PFUNC)(void*);
void signal_handler( int signo );

G_DEFINE_TYPE(ActivationDbus, activation_dbus, G_TYPE_OBJECT);

ActivationDbus * activation_dbus_new(void)
{
    return (ActivationDbus*) g_object_new(ACTIVATION_TYPE_DBUS, NULL);
}

void activation_dbus_init(ActivationDbus * dbus)
{
}


void activation_dbus_class_init(ActivationDbusClass * kclass)
{
    signals[ACTIVATION_RESULT] =
            g_signal_new ("activation_result",
            G_OBJECT_CLASS_TYPE (kclass),
                    G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
                    0,
                    NULL, NULL,
                    g_cclosure_marshal_VOID__INT,
                    G_TYPE_NONE, 1, G_TYPE_INT);
}

//提供序列号
gint activation_dbus_serial_number(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar *serial = NULL;
    gint i =0;
    serial = kylin_activation_get_serial_number(&i);
    dbus_g_method_return(ret_value, serial, i);
    g_free(serial);
    return 0;
}

//提供注册码
gint activation_dbus_register_number(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar * register_number = NULL;
    gint i =0;
    register_number = kylin_activation_get_register_number(&i);
    dbus_g_method_return(ret_value, register_number, i);
    g_free(register_number);
    return 0;
}

//提供激活码
gint activation_dbus_qrcode(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar * qrcode = NULL;
    gint i =0;
    qrcode = kylin_activation_get_qrcode(&i);
    dbus_g_method_return(ret_value, qrcode, i);
    g_free(qrcode);
    return 0;
}

//提供激活接口
gint activation_dbus_activate(ActivationDbus * dbus, gchar * code, DBusGMethodInvocation * ret_value)
{
    gint activate = 0;
    activate = kylin_activation_activate_system(code);
    dbus_g_method_return(ret_value, activate);
    g_signal_emit (dbus, signals[ACTIVATION_RESULT], 0, activate);
//    g_free(activate);
    return 0;
}

//提供激活日期
gint activation_dbus_date(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
//    gint state = 0;
    gchar * state = "inactive ";
    gint i =0;
    state =kylin_activation_get_old_expire_date(&i);
    dbus_g_method_return(ret_value, state,i);
    g_free(state);
    return 0;
}

//提供激活状态
gint activation_dbus_status(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gint state = 1;
    gint i =1;
    state =kylin_activation_activate_status(&i);
    dbus_g_method_return(ret_value, state,i);

    return 0;
}

//验证激活
gint activation_dbus_trial_status(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gint state = 1;
    gint i =1;
    state =kylin_activation_trial_status(&i);
    dbus_g_method_return(ret_value, state,i);

    return 0;
}

//新检测序列号
gint activation_dbus_can_set_serial(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gint serial = 0;
    gint i =0;
    serial = kylin_activation_can_set_serial_number(&i);
    dbus_g_method_return(ret_value, serial, i);
    return 0;
}

//新获取注册码接口
gint activation_dbus_new_register_number(ActivationDbus * dbus, gchar * code, DBusGMethodInvocation * ret_value)
{
    gchar * register_number = NULL;
    gint i =0;
    register_number = kylin_activation_get_register_number_with_serial(code,&i);
    dbus_g_method_return(ret_value, register_number, i);
    g_free(register_number);
    return 0;
}

//新获取激活码接口
gint activation_dbus_new_qrcode(ActivationDbus * dbus, gchar * code, DBusGMethodInvocation * ret_value)
{
    gchar * register_number = NULL;
    gint i =0;
    register_number = kylin_activation_get_qrcode_with_serial(code,&i);
    dbus_g_method_return(ret_value, register_number, i);
    g_free(register_number);
    return 0;
}

//新激活接口
gint activation_dbus_new_activate(ActivationDbus * dbus, gchar * serial, gchar * code, DBusGMethodInvocation * ret_value)
{
    gint activate = 0;
    activate = kylin_activation_activate_system_with_serial(serial, code);
    dbus_g_method_return(ret_value, activate);
     g_signal_emit (dbus, signals[ACTIVATION_RESULT], 0, activate);
//    g_free(activate);
    return 0;
}

//获取硬件信息
gint activation_dbus_get_encrypted_hardware_info(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar * register_number = NULL;
    gint i =0;
    register_number = kylin_activation_get_encrypted_hardware_info(&i);
    dbus_g_method_return(ret_value, register_number, i);
    g_free(register_number);
    return 0;
}

//获取硬盘序列号
gint activation_dbus_get_harddisk_id(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar * register_number = NULL;
    gint i =0;
    register_number = hardware_info_harddisk_id(&i);
    dbus_g_method_return(ret_value, register_number, i);
    g_free(register_number);
    return 0;
}

//获取网卡mac
gint activation_dbus_get_interface_mac(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar * register_number = NULL;
    gint i =0;
    register_number = hardware_info_network_interface_mac(&i);
    dbus_g_method_return(ret_value, register_number, i);
    g_free(register_number);
    return 0;
}

//获取系统UUID
gint activation_dbus_get_system_uuid(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar * register_number = NULL;
    gint i =0;
    register_number = hardware_info_system_uuid(&i);
    dbus_g_method_return(ret_value, register_number, i);
    g_free(register_number);
    return 0;
}


//获取客户单位
gint activation_dbus_get_customer(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar * register_number = NULL;
    gint i =0;
    register_number = kylin_activation_get_customer(&i);
    dbus_g_method_return(ret_value, register_number, i);
    g_free(register_number);
    return 0;
}

//设置客户单位
gint  activation_dbus_set_customer(ActivationDbus * dbus, gchar * customer, DBusGMethodInvocation * ret_value)
{
    gint activate = 0;
    activate = kylin_activation_set_customer(customer);
    dbus_g_method_return(ret_value, activate);
//    g_free(activate);
    return 0;
}

//导入授权文件
gboolean activation_dbus_import_auth_file(ActivationDbus *dbus, gchar *path, DBusGMethodInvocation *ret_value)
{
    gboolean ret=FALSE;
    char *dpath=NULL;
    GFile *sgfile=g_file_new_for_path(path);

//    int size=sizeof(path)+15;
    char cmd1[512]="chmod 664 ";
    strcat(cmd1,path);
    g_print("Hcy Test.......%s\n", cmd1);

    system(cmd1);
    if(g_str_has_suffix(g_file_get_basename(sgfile),".zip") ||
            g_str_has_suffix(g_file_get_basename(sgfile),".gz") ||
            g_str_has_suffix(g_file_get_basename(sgfile),".bz2"))
    {
        dbus_g_method_return(ret_value,FALSE);
        return FALSE;
    }
    else if(g_strrstr(g_strup(g_file_get_basename(sgfile)),"LICENSE")!=NULL)
        dpath="/etc/LICENSE";
    else if(g_strrstr(g_strdown(g_file_get_basename(sgfile)),"kyinfo")!=NULL)
        dpath="/etc/.kyinfo";
    else
    {
        dbus_g_method_return(ret_value,FALSE);
        return FALSE;
    }

    //复制授权文件
    if(dpath!=NULL)
    {
        GFile *dgfile=g_file_new_for_path(dpath);
        ret=g_file_copy(sgfile,dgfile,G_FILE_COPY_OVERWRITE,NULL,NULL,NULL,NULL);
        dbus_g_method_return(ret_value,ret);
        g_signal_emit (dbus, signals[ACTIVATION_RESULT], 0, 0);
        g_object_unref(dgfile);
    }

    g_object_unref(sgfile);
    return ret;
}

//删除激活文件
gboolean activation_dbus_remove_activation_file(ActivationDbus *dbus, DBusGMethodInvocation *ret_value)
{
    GFile *gfile_1=g_file_new_for_path("/etc/.kyactivation");
    GFile *gfile_2=g_file_new_for_path("/etc/.kyhwid");
    if(g_file_delete(gfile_1,NULL,NULL) && g_file_delete(gfile_2,NULL,NULL))
    {
        dbus_g_method_return(ret_value,TRUE);
        g_signal_emit (dbus, signals[ACTIVATION_RESULT], 0, 0);
    }
    else
        dbus_g_method_return(ret_value,FALSE);
    g_object_unref(gfile_1);
    g_object_unref(gfile_2);
}

//删除授权文件
gboolean activation_dbus_remove_license_file(ActivationDbus *dbus, DBusGMethodInvocation *ret_value)
{
    GFile *gfile_1=g_file_new_for_path("/etc/LICENSE");
    GFile *gfile_2=g_file_new_for_path("/etc/.kyinfo");
    if(g_file_delete(gfile_1,NULL,NULL) && g_file_delete(gfile_2,NULL,NULL))
        dbus_g_method_return(ret_value,TRUE);
    else
        dbus_g_method_return(ret_value,FALSE);
    g_object_unref(gfile_1);
    g_object_unref(gfile_2);
}

gint activation_dbus_get_service_tag(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar *buf=kylin_activation_get_service_tag();
    dbus_g_method_return(ret_value,buf);
    g_free(buf);
    return 0;
}

gint activation_dbus_get_vendor(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar *buf=kylin_activation_get_vendor();
    dbus_g_method_return(ret_value,buf);
    g_free(buf);
    return 0;
}

gint activation_dbus_get_model(ActivationDbus *dbus, DBusGMethodInvocation *ret_value)
{
    gchar *buf=kylin_activation_get_model();
    dbus_g_method_return(ret_value,buf);
    g_free(buf);
    return 0;
}

gint activation_dbus_check_oem(ActivationDbus *dbus, DBusGMethodInvocation *ret_value)
{
    if(-1==kylin_activation_check_oem())
        dbus_g_method_return(ret_value,FALSE);
    else
        dbus_g_method_return(ret_value,TRUE);
    return 0;
}

gint activation_dbus_license_check(ActivationDbus * dbus, gchar * l_file, gchar * i_file, DBusGMethodInvocation * ret_value)
{
    gint ret=kylin_activation_license_check(l_file,i_file);
    dbus_g_method_return(ret_value,ret);
    return 0;
}

gint activation_dbus_trial_date(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gchar * state = "tria";
    gint i =0;
    state =kylin_activation_get_trial_date(&i);
    dbus_g_method_return(ret_value, state,i);
    g_free(state);
    return 0;
}

//dbus测试
gint activation_dbus_work(ActivationDbus * dbus, gchar * path, DBusGMethodInvocation * ret_value)
{
    g_print("Kobe Test.......%s\n", path);
    //gint ret = 0;
    gchar *ret = NULL;

    //kobe test : write some bytes to a file
    //ret = player();//kobe: please use your function
    //ret = g_settings_get_string();
    //g_strdup()
    ret = g_strdup_printf ("%s Wh", "kobe");
    dbus_g_method_return(ret_value, ret, 24);
    g_free(ret);
    //dbus_g_method_return(ret_value, ret);
    return 0;
}

//退出
gint activation_dbus_exit(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
	gint i = 0, ret = 0;
	dbus_g_method_return(ret_value, ret,i);

	//sleep(2);
	exit(0);
	return ret;
}

//测试
gint activation_dbus_find_ukey(ActivationDbus * dbus, DBusGMethodInvocation * ret_value)
{
    gint state = 1;
    gint i = 1;
    state = kylin_activation_find_ukey(&i);
    dbus_g_method_return(ret_value,state,i);

    return 0;
}

static GMainLoop *loop = NULL;
ActivationDbus * dbus;

//dbus初始化
int dbus_init(void)
{
    DBusGConnection * connection = NULL;
    DBusConnection *connect;
	DBusGProxy * dbus_proxy = NULL;
	GError * error = NULL;
	guint request_name_result;
	gint ret;

    g_type_init();
    g_thread_init(NULL);
    dbus_g_thread_init();

    dbus = (ActivationDbus*)activation_dbus_new();
    loop = g_main_loop_new(NULL, FALSE);
	
    connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
	if(connection == NULL){
		g_error("%s", error->message);
		g_error_free(error);
		error = NULL;
		goto out;
	}

	dbus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS,
						DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);

	ret = dbus_g_proxy_call(dbus_proxy, "RequestName", &error,
                G_TYPE_STRING, ACTIVATION_DBUS_NAME,
				G_TYPE_UINT,
				DBUS_NAME_FLAG_DO_NOT_QUEUE,
				G_TYPE_INVALID,
				G_TYPE_UINT, &request_name_result,
				G_TYPE_INVALID);
	if(!ret){
		g_error("RequestName failed:%s", error->message);
		g_error_free(error);
		error = NULL;
		exit(EXIT_FAILURE);
	}

	g_object_unref(G_OBJECT(dbus_proxy));
	
	/* already running */
	if(request_name_result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
		exit(EXIT_FAILURE);

    dbus_g_object_type_install_info(ACTIVATION_TYPE_DBUS,
                    &dbus_glib_activation_dbus_object_info);
    dbus_g_connection_register_g_object(connection, ACTIVATION_DBUS_PATH,
                    G_OBJECT(dbus));

    signal( SIGINT, &signal_handler);
    g_main_loop_run(loop);
	
out:
    g_main_loop_unref(loop);
    g_object_unref(dbus);
	return 1;	
}


void signal_handler( int signo ){
    g_main_loop_unref(loop);
    g_object_unref(dbus);
	fprintf(stderr, "get out now\n");
	exit(1);
}
